package com.zkh.myutils.utils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import com.zkh.myutils.code.CoderUtils;
import com.zkh.myutils.io.log.Logger;

/**
 * 路径相关工具类
 * @author zkh
 */
public class PathUtils {

	/**
	 * 获取类所在路径。如果类来自jar包，返回jar包的File对象，否则返回ClassLoader路径的File对象。
	 * @param clazz
	 * @return
	 */
	public static File getClassPath(Class<?> clazz) {
		//当前应用路径
		String path = CoderUtils.decodeURL(clazz.getProtectionDomain().getCodeSource().getLocation().getPath());
		//返回
		return new File(path);
	}
	
	/**
	 * 加载包下所有类名称（全类名）
	 * @param classLoader 类加载器
	 * @param pack 指定包。如 com/test/utils
	 * @return
	 */
	public static List<String> getAllClassNames(ClassLoader classLoader, String pack){
		return getAllClassNames(classLoader, pack, ".+");
	}
	
	/**
	 * 加载包下所有类满足正则的名称（全类名）
	 * @param pack 指定包。如 com/test/utils
	 * @param classLoader 类加载器
	 * @param pattern 类名正则
	 * @return
	 */
	public static List<String> getAllClassNames(ClassLoader classLoader, String pack, String pattern){
		//容器
		List<String> list = new ArrayList<>();
		//资源变动
		URL url;
		//不为空，则开始解析
		if(StringUtils.isNotEmpty(pack) && (url = classLoader.getResource(pack))!=null) {
			//类型
			String type = url.getProtocol();
			//路径
			String path = CoderUtils.decodeURL(url.getPath());
			//格式化包
			if(pack.endsWith("/")) pack=pack.substring(0, pack.length()-1);
			//文件
			if("file".equals(type)) {
				//加载目录
				loadDirFiles(new File(path), pack, pattern+"\\.class", list);
			}//jar包
			else {
				try {
					loadJarFiles(new JarFile(path.substring(0, path.indexOf('!'))), pack, pattern+"\\.class", list);
				} catch (IOException e) {
					Logger.error(e);
				}
			}
		}
		return list;
	}
	
	/**
	 * 加载目录下的所有类文件
	 * @param dir
	 */
	private static void loadDirFiles(File dir, String prefix, String pattern, List<String> container) {
		//展示文件或目录名
		String[] list = dir.list();
		//不为空
		if(list!=null) {
			//遍历
			for(String file: list) {
				//文件
				File curr = new File(dir, file);
				//为目录
				if(curr.isDirectory()) {
					loadDirFiles(curr, prefix + "/" + file, pattern, container);
				}//文件，匹配文件名
				else if(file.matches(pattern)){
					container.add((prefix + "/" + file.substring(0, file.length()-6)).replace('/', '.'));
				}
			}
		}
	}
	
	/**
	 * 加载目录下的所有类文件
	 * @param dir
	 */
	private static void loadJarFiles(JarFile jarFile, String prefix, String pattern, List<String> container) {
		//获取遍历器
		Enumeration<JarEntry> jarEntry = jarFile.entries();
		//开始遍历
		while(jarEntry.hasMoreElements()) {
			//当前
			JarEntry tmpEntry = jarEntry.nextElement();
			//名称
			String name = tmpEntry.getName();
			//匹配
			if(name.matches(prefix + ".+/" + pattern)) {
				container.add(name.substring(0, name.length()-6).replace('/', '.'));
			}
		}
	}
	
	/**
	 * 获取系统临时目录
	 * @return
	 */
	public static File getTempDir() {
		return new File(System.getProperty("java.io.tmpdir"));
	}
	
	/**
	 * 获取一个临时文件，文件名随机
	 * @return
	 */
	public static File getTempFile() throws IOException{
		return getTempFile(Utils.getUUID() + ".tmp");
	}
	
	/**
	 * 获取一个临时文件
	 * @param filename 文件名
	 * @return
	 */
	public static File getTempFile(String filename) throws IOException{
		return getTempFileFromDir(null, filename);
	}
	
	/**
	 * 获取一个临时文件，文件名随机
	 * @param subdir 指定子目录
	 * @return
	 * @throws IOException
	 */
	public static File getTempFileFromDir(String subdir) throws IOException{
		return getTempFileFromDir(null, Utils.getUUID() + ".tmp");
	}
	
	/**
	 * 获取一个临时文件
	 * @param subdir 指定子目录
	 * @param filename 文件名
	 * @return
	 * @throws IOException
	 */
	public static File getTempFileFromDir(String subdir, String filename) throws IOException{
		//目录
		File base = getTempDir();
		//子目录
		if(StringUtils.isNotEmpty(subdir)) {
			//子目录
			base = new File(base, subdir);
			//创建
			if(!base.isDirectory()) {
				base.mkdir();
			}
		}
		//临时文件
		File tempFile = new File(base, filename);
		//创建文件
		tempFile.createNewFile();
		//返回
		return tempFile;
	}
	
	/**
	 * 获取系统user.dir路径
	 * @return
	 */
	public static File getUserDir() {
		return new File(System.getProperty("user.dir"));
	}
}
